#include"rtp.h"
#define USER_AGNET "RTP Client v1.0"
#define EXPIRE_SEC 60
#define RTSP_VERSION "RTSP/1.0"
#include"tcp_cli.h"	
#include"stdio.h"
#include<string.h>
#include<stdarg.h>

#ifdef __cplusplus
extern  "C"{
#endif

char arrAction[][32] = {
	"OPTIONS" ,
	"DESCRIBE" , 
	"SETUP" ,
	"TEARDOWN",
	"PLAY" ,
	"PAUSE", 
	"SCALE" ,
	"GET_PARAMETER" 
};
char arrHeaderDefine[][128] = {
"Accept",
"Accept - Encoding",
"Accept - Language",
"Allow",
"Authorization",
"Bandwidth",
"Blocksize",
"Cache - Control",
"Conference",
"Connection",
"Content - Base",
"Content - Encoding",
"Content - Language",
"Content - Length",
"Content - Location",
"Content - Type",
"CSeq",
"Date",
"Expires",
"From",
"Host",
"If - Match",
"If - Modified - Since",
"Last - Modified",
"Location",
"Proxy - Authenticate",
"Proxy - Require",
"Public",
"Range",
"Referer",
"Retry - After",
"Require",
"RTP - Info",
"Scale",
"Speed",
"Server",
"Session",
"Timestamp",
"Transport",
"Unsupported",
"User - Agent",
"Vary",
"Via",
"WWW - Authenticate "
};
const char pattern_url[] = "[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}";
const char pattern_port[] = ":\\d{1,}";


int _addCRLF(char *p){
	if(NULL == p){
		return -1;
	}
	strcat(p, "\r\n\r\n");
	int iLen = strlen(p);
	if(iLen > MAX_BUF){
		return -1; 
	}

	return 0; 
}
int setHeader(char *dest,enum RtspHeader header,char *format,...){
	char temp[512]="\0";
	char pTmp[MAX_BUF]={};
	va_list arg; 
	va_start(arg, format);
	int iLen = strlen(dest);
	if(iLen >MAX_BUF){
		return -1;
	}

	strcpy(pTmp,dest);

	if(NULL == format || dest == NULL){
		return -1;
	}
	while (*format)
	{
		char ret = *format;
		if (ret == '%')
		{
			switch (*++format)
			{
				case 'c':
				{
					char ch = va_arg(arg, char);
					strcat(temp, &ch);
					break;
				}
				case 's':
				{
					char *pc = va_arg(arg, char *);
					strcat(temp, pc);
					break;
				}
				case 'd':
				{
					char iTmp[12]="\0";
					int i = va_arg(arg, int);
					SPRINTF(iTmp, "%d", i);
					strcat(temp, iTmp);
					break;
				}
				default:
					break;
			}
		}
		else
		{
			char cTemp = *format;
			temp[strlen(temp)] = cTemp;
			temp[strlen(temp) + 1] = '\0'; 
		}
		format++;
	}
	SPRINTF(dest,"%s ",arrAction[header]);
	SPRINTF(dest + strlen(dest),"%s",temp);

	strcat(dest,pTmp);
	va_end(arg);	
	return 0;
}
/*
static int _reqOption(RtspClient *tRtp, RtspResponse *p, int iCeq);
static int _reqDescripe(RtspClient *tRtp, int iCeq);
static int _reqSetup(RtspClient *tRtp, int iCeq);
static int _reqTearDown(RtspClient *tRtp, int iCeq);
static int _reqPlay(RtspClient *tRtp, int iCeq);
static int _reqPause(RtspClient *tRtp, int iCeq);
static int _reqScale(RtspClient *tRtp, int iCeq);
static int _reqGetPara(RtspClient *tRtp, int iCeq);
*/
static int _reqOption(RtspClient *tRtp,RtspResponse *p,int iCeq) {
	int iLen = 0;
	char req[BUFF_LEN] = "";
	if (NULL == tRtp || NULL == p) {
		return -1;
	}
	setHeader(req, OPTIONS, "%s RTSP/1.0","rtsp://192.168.2.107:5544");
	setOptPara(req, "CSeq", "%d",tRtp->iCSeq);
	//setOpt(req, arrHeaderDefine[Require], "implicit-play");
	//setOpt(req, arrHeaderDefine[ProxyRequire], "gzipped-messages");
	setOpt(req, arrHeaderDefine[UserAgent], USER_AGNET);
	_addCRLF(req);
	printf("%s\n", req);
	TcpSend(&tRtp->m_conn, req,strlen(req));
	memset(req, 0, BUFF_LEN);
	TcpRecv(&tRtp->m_conn, req,BUFF_LEN);
	memcpy(p->m_raw_buff, req, strlen(p->m_raw_buff));
	tRtp->iCSeq ++;

	//send(tRtp->m_conn.CientSocket,)
}
/*
@author cyzheng

*/
static int _reqDescripe(RtspClient *tRtp,RtspResponse *p, int iCeq){
	int iLen = 0;
	char req[BUFF_LEN] = "";
	if (NULL == tRtp || NULL == p) {
		return -1;
	}
	setHeader(req, DESCRIBE, "%s:%d RTSP/1.0",tRtp->pAddr,tRtp->port);
	tRtp->iCSeq ++;
	setOptPara(req, "CSeq", "%d",tRtp->iCSeq);
	setOpt(req, arrHeaderDefine[Accept], "application/sdp, application/rtsl, application/mheg");
	_addCRLF(req);
	TcpSend(&tRtp->m_conn, req,strlen(req));

	printf("%s\n", req);

	memset(req, 0, BUFF_LEN);
	int iRecvd = TcpRecv(&tRtp->m_conn, req,BUFF_LEN);
	memcpy(p->m_raw_buff, req, strlen(req));
	regmatch_t reg[3];
	if( 0 <RegrexMatching("rtsp://[^]{0,50}",req,reg))
	{

	}else{
		
	}
	return 0;
}
static int _reqSetup(RtspClient *tRtp,RtspResponse *p, int iCeq){
	int iLen = 0;
	char req[BUFF_LEN] = "";
	if (NULL == tRtp || NULL == p) {
		return -1;
	}
	setOptPara(req, "", "SETUP  %s:%d RTSP/1.0",tRtp->pAddr,tRtp->port);
	tRtp->iCSeq ++;
	setOptPara(req, "CSeq", "%d",tRtp->iCSeq);
	setOpt(req, arrHeaderDefine[Transport], "RTP/AVP;unicast;client_port=4588-4589");

	TcpSend(&tRtp->m_conn, req,strlen(req));
	memset(req, 0, BUFF_LEN);
	TcpRecv(&tRtp->m_conn, req,BUFF_LEN);
	memcpy(p->m_raw_buff, req, strlen(p->m_raw_buff));
	return 0;
}
static int _reqTearDown(RtspClient *tRtp,RtspResponse *p, int iCeq){
	int iLen = 0;
	char req[BUFF_LEN] = "";
	if (NULL == tRtp || NULL == p) {
		return -1;
	}
	setOpt(req, "", "TEARDOWN rtsp://example.com/fizzle/foo RTSP/1.0");
	tRtp->iCSeq ++;
	setOptPara(req, "CSeq", "%d",tRtp->iCSeq);
	setOptPara(req, arrHeaderDefine[Session],"%d",12345678);

	TcpSend(&tRtp->m_conn, req,strlen(req));
	memset(req, 0, BUFF_LEN);
	TcpRecv(&tRtp->m_conn, req,BUFF_LEN);
	memcpy(p->m_raw_buff, req, strlen(p->m_raw_buff));
	return 0;
}
/*
@author : cyzheng
*/
int setOpt(char *ptmp,char *key,char *value) {
	if (NULL== ptmp || NULL == key || NULL == value) {
		return -1;
	}

	char temp[1024] = "";
	SPRINTF(temp,"\r\n%s : %s",key,value);
	if (strlen(ptmp) +strlen(temp) > BUFF_LEN) {
		return -1;
	}
	strcat(ptmp, temp);
	return 0;
}
/*
@author cyzheng

*/
int setOptPara(char *ptmp, char *key, char *format,...) {
	char temp[BUFF_LEN] = "";
	char temp2[BUFF_LEN] = "";

	va_list arg;
	va_start(arg, format);
	if (NULL == ptmp || NULL == key || NULL == format) {
		return -1;
	}
	while (*format)
	{
		char ret = *format;
		if (ret == '%')
		{
			switch (*++format)
			{
				case 'c':
				{
					char ch = va_arg(arg, char);
					strcat(temp, &ch);
					break;
				}
				case 's':
				{
					char *pc = va_arg(arg, char *);
					strcat(temp, pc);
					break;
				}
				case 'd':
				{
					char iTmp[3];
					int i = va_arg(arg, int);
					SPRINTF(iTmp, "%d", i);
					strcat(temp, iTmp);
				}
				default:
					break;
			}
		}
		else
		{
			char cTemp = *format;
			strcat(temp, &cTemp);
		}
		format++;
	}
	va_end(arg);
	SPRINTF(temp2, "\r\n%s: %s", key, temp);
	if (strlen(ptmp) + strlen(temp) > BUFF_LEN) {
		return -1;
	}
	strcat(ptmp, temp2);
	return 0;
}
/*
@author cyzheng

*/
int appendOpt(RtspResponse *p, char *key, char *value) {
	if (NULL == p || NULL == key || NULL == value) {
		return -1;
	}
}
/*
	@author cyzheng
*/
int  RtspConnect(RtspClient *p,  const char *pAddr, int Port){
	regmatch_t pm[3];
	int iRet  = -1;
	if (NULL == p || NULL == pAddr) {
		return -1;
	}
	if (NULL!=strstr(pAddr, "rtsp")){
		char pRaw_ip[30];
		char pRaw_port[30];
		int len = RegrexMatching(pattern_url,pAddr,pm);
		if(len  == 1){
			memcpy(pRaw_ip, &pAddr[pm->rm_so], pm->rm_eo-pm->rm_so);
		}
 		len = RegrexMatching(pattern_port,pAddr,pm);
		if(len  == 1)
			memcpy(pRaw_port, &pAddr[pm->rm_so], pm->rm_eo-pm->rm_so);		
		strcpy(p->pAddr,pRaw_ip);
		iRet = TcpConnect(&p->m_conn, pRaw_ip, Port);
		if (iRet < 0) {
			return -1;
		}
		strcpy(p->pAddr, pAddr);	


		}else{
			p->port = Port;
			iRet = TcpConnect(&p->m_conn, pAddr, Port);
			if (iRet < 0) {
				return -1;
			}
			strcpy(p->pAddr, pAddr);	
	}
	return iRet;
}
/*

*/
void RtspClose(RtspClient *tRtp) {
	if (NULL == tRtp) {

	}
	TcpClose(&tRtp->m_conn);
}
/*

*/
void RtspDo(RtspClient *tRtp, enum RtspHeader code, RtspResponse *p) {
	if (NULL == tRtp) {

	}
	switch (code) {
	case      OPTIONS:
		_reqOption(tRtp, p, tRtp->iCSeq);
		break;
	case      DESCRIBE:
		_reqDescripe(tRtp, p, tRtp->iCSeq);
		break;
	case	SETUP:
		break;
	case	TEARDOWN:
		break;
	case	PLAY:
		break;
	case	PAUSE:
		break;
	case	SCALE:
		break;
	case	GET_PARAMETER:
		break;
	}
}
#ifdef __cplusplus
}
#endif